package com.sansecy.video.player;

import android.content.Context;
import android.net.Uri;
import android.util.Log;
import android.view.Surface;

import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSourceFactory;
import com.google.android.exoplayer2.source.MergingMediaSource;
import com.google.android.exoplayer2.source.SingleSampleMediaSource;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.rtsp.RtspMediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.EventLogger;
import com.google.android.exoplayer2.video.VideoSize;
import com.google.common.collect.Lists;
import com.sansecy.base.file.FileUtilsKt;
import com.sansecy.video.TrackSelectionDialog;

import org.jetbrains.annotations.NotNull;

import java.util.Locale;

public class ExoPlayer implements IPlayer {

    private final Context mContext;
    SimpleExoPlayer player;
    private Uri mUri;
    private TrackGroupArray lastSeenTrackGroupArray;
    private onErrorListener mOnErrorListener;
    private final DefaultTrackSelector mTrackSelector;
    private final MediaSourceFactory mMediaSourceFactory;
    private boolean mSetupSubtitle;

    public ExoPlayer(Context context) {
        mContext = context;
        mMediaSourceFactory = new DefaultMediaSourceFactory(context);

        mTrackSelector = new DefaultTrackSelector(context);
        player = new SimpleExoPlayer.Builder(context, ExoPlayerUtil.buildRenderersFactory(context))
                .setTrackSelector(mTrackSelector)
                .setMediaSourceFactory(mMediaSourceFactory)
                .build();
        player.addAnalyticsListener(new EventLogger(mTrackSelector));
        player.addListener(new Player.Listener() {
            @Override
            public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
                if (trackGroups != lastSeenTrackGroupArray) {
                    MappedTrackInfo mappedTrackInfo = mTrackSelector.getCurrentMappedTrackInfo();
                    if (mappedTrackInfo != null) {
                        if (mappedTrackInfo.getTypeSupport(C.TRACK_TYPE_VIDEO)
                                == MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
                            if (mOnErrorListener != null) {
                                mOnErrorListener.onError(UNSUPPORTED_VIDEO_TRACKS);
                            }
                        }
                        if (mappedTrackInfo.getTypeSupport(C.TRACK_TYPE_AUDIO)
                                == MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
                            if (mOnErrorListener != null) {
                                mOnErrorListener.onError(UNSUPPORTED_AUDIO_TRACKS);
                            }
                        }
                        if (mappedTrackInfo.getTypeSupport(C.TRACK_TYPE_TEXT)
                                == MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
                            if (mOnErrorListener != null) {
                                mOnErrorListener.onError(UNSUPPORTED_TEXT_TRACKS);
                            }
                        }
                    }
                    lastSeenTrackGroupArray = trackGroups;
                }
            }

            @Override
            public void onPlaybackStateChanged(int state) {
                if (state == Player.STATE_READY) {
                    if (mSetupSubtitle) {
                        DefaultTrackSelector.Parameters initialParameters = mTrackSelector.getParameters();
                        DefaultTrackSelector.ParametersBuilder builder = initialParameters.buildUpon();
                        MappedTrackInfo mappedTrackInfo = Assertions.checkNotNull(mTrackSelector.getCurrentMappedTrackInfo());
//                        DefaultTrackNameProvider defaultTrackNameProvider = new DefaultTrackNameProvider(mContext.getResources());
                        //遍历轨道数量
                        for (int i = 0; i < mappedTrackInfo.getRendererCount(); i++) {
                            builder.clearSelectionOverrides(/* rendererIndex= */ i);
                            //查找视频音频字幕轨道
                            if (TrackSelectionDialog.showTabForRenderer(mappedTrackInfo, i)) {
                                //获取渲染器的类型，如视频，音频，字幕
                                int trackType = mappedTrackInfo.getRendererType(/* rendererIndex= */ i);
                                boolean rendererDisabled = initialParameters.getRendererDisabled(/* rendererIndex= */ i);
                                //获取trackType对应类型的轨道组，TrackGroupArray表示这条轨道组里有几条视频轨道，音频轨，字幕轨
                                TrackGroupArray trackGroups = mappedTrackInfo.getTrackGroups(/* rendererIndex= */ i);
                                DefaultTrackSelector.SelectionOverride selectionOverride = initialParameters.getSelectionOverride(/* rendererIndex= */ i, trackGroups);

                                for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) {
                                    TrackGroup trackGroup = trackGroups.get(groupIndex);
                                    for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
//                                        Format format = trackGroup.getFormat(trackIndex);
//                                    String trackName = defaultTrackNameProvider.getTrackName(format);
                                        if (trackType == C.TRACK_TYPE_TEXT) {
                                            rendererDisabled = false;
                                            selectionOverride = new DefaultTrackSelector.SelectionOverride(groupIndex, trackIndex);
                                        }
                                    }
                                }
                                builder.setRendererDisabled(
                                        /* rendererIndex= */ i,
                                        rendererDisabled);
                                if (selectionOverride != null) {
                                    builder.setSelectionOverride(
                                            /* rendererIndex= */ i,
                                            trackGroups,
                                            selectionOverride);
                                }
                            }
                        }
                        mTrackSelector.setParameters(builder);
                        mSetupSubtitle = false;
                    }
                }
            }
        });
    }

    private static final String TAG = "ExoPlayer-App";

    public SimpleExoPlayer getSimplePlayer() {
        return player;
    }

    @Override
    public void setUri(Uri uri) {
        mUri = uri;
//        DefaultHttpDataSourceFactory dataSourceFactory = new DefaultHttpDataSourceFactory(Util.getUserAgent(mContext, "MIGU"));
//        ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(uri);
//        player.setMediaItem(MediaItem.fromUri(uri));
        MediaSource mediaSource =
                new RtspMediaSource.Factory()
                        .createMediaSource(MediaItem.fromUri(uri));
//        MediaItem.Builder builder = new MediaItem.Builder();
//        builder.setUri(uri);
//        String subtitleUri = PlayerUtil.getSavedPlaySubtitleUri(mContext, uri.getPath());
//        String mimeType = "";
//        if (!TextUtils.isEmpty(subtitleUri)) {
//            if (subtitleUri.endsWith("ass")) {
//                mimeType = MimeTypes.TEXT_SSA;
//            } else if (subtitleUri.endsWith("srt")) {
//                mimeType = MimeTypes.APPLICATION_SUBRIP;
//            }
//        }
//        MediaItem.Subtitle subtitle = new MediaItem.Subtitle(Uri.parse(subtitleUri), mimeType, Locale.getDefault().getLanguage());
//        builder.setSubtitles(Lists.newArrayList(subtitle));
//        player.setMediaItem(builder.build());
        player.setMediaSource(mediaSource);
        player.prepare();
        mSetupSubtitle = true;
    }

    @Override
    public void setUri(Uri uri, String subtitleUrl) {
        mUri = uri;
        MediaItem.Subtitle subtitle =
                new MediaItem.Subtitle(
                        Uri.parse(subtitleUrl),
                        "text/plain", // The correct MIME type.
                        null, // The subtitle language. May be null.
                        C.SELECTION_FLAG_FORCED); // Selection flags for the track.

        MediaItem mediaItem = new MediaItem.Builder()
                .setUri(uri)
                .setSubtitles(Lists.newArrayList(subtitle))
                .build();
//        MediaItem mediaItem = MediaItem.fromUri(mUri);
        player.setMediaItem(mediaItem);
        player.prepare();
    }

    @Override
    public void setVolume(float volume) {
        player.setVolume(volume);
    }

    @Override
    public long getDuration() {
        return player.getDuration();
    }

    @Override
    public long getCurrentPosition() {
        return player.getCurrentPosition();
    }

    @Override
    public void seekTo(long position) {
        player.seekTo(position);
    }

    @Override
    public boolean isPlaying() {
        return player.isPlaying();
    }

    @Override
    public void start() {
        player.play();
    }

    @Override
    public void pause() {
        player.pause();
    }

    @Override
    public void stop() {
        player.stop();
    }

    @Override
    public void release() {
        player.release();
    }

    @Override
    public void setDisplay(Surface surface) {
        player.setVideoSurface(surface);
    }

    @Override
    public void prepareAsync() {
        player.prepare();
    }

    @Override
    public void setOnVideSizeChangeListener(OnVideoSizeChangedListener onVideoSizeChangedListener) {
        player.addListener(new Player.Listener() {
            @Override
            public void onVideoSizeChanged(@NotNull VideoSize videoSize) {
                if (onVideoSizeChangedListener != null) {
                    onVideoSizeChangedListener.onVideoSizeChanged(videoSize.width, videoSize.height);
                }
            }
        });
    }

    @Override
    public void setOnBufferListener(OnBufferListener onBufferListener) {
        player.addListener(new Player.Listener() {
            @Override
            public void onPlaybackStateChanged(int state) {
                if (onBufferListener != null) {
                    if (state == Player.STATE_BUFFERING) {
                        onBufferListener.onBufferStart();
                    } else if (state == Player.STATE_READY) {
                        onBufferListener.onBufferEnd();
                    }
                }
            }
        });
    }

    @Override
    public void setOnCompletionListener(OnCompletionListener onCompletionListener) {
        player.addListener(new Player.Listener() {
            @Override
            public void onPlaybackStateChanged(int state) {
                if (state == Player.STATE_ENDED) {
                    if (onCompletionListener != null) {
                        onCompletionListener.onCompletion();
                    }
                }
            }
        });
    }

    @Override
    public int getBufferPercentage() {
        return player.getBufferedPercentage();
    }

    @Override
    public void setSubtitle(String uri, String mimeType) {
        MediaSource contentMediaSource = mMediaSourceFactory.createMediaSource(MediaItem.fromUri(mUri));
        MediaSource subtitleSource = new SingleSampleMediaSource.Factory(new DefaultDataSourceFactory(mContext))
                .createMediaSource(new MediaItem.Subtitle(Uri.parse(uri), mimeType, Locale.getDefault().getLanguage()), C.TIME_UNSET);
        MergingMediaSource mergedSource = new MergingMediaSource(true, contentMediaSource, subtitleSource);
        player.setMediaSource(mergedSource);
        PlayerUtil.seekTo(mContext, this, mUri.getPath());
        PlayerUtil.savePlaySubtitle(mContext, mUri.getPath(), uri);
        mSetupSubtitle = true;
    }

    @Override
    public Object getPlayer() {
        return player;
    }

    @Override
    public IPlayer getIPlayer() {
        return this;
    }

    @Override
    public boolean isAudio() {
        if (mUri != null) {
            return FileUtilsKt.getMimeType(mUri.toString()).contains("audio");
        }
        return false;
    }

    @Override
    public void setOnErrorListener(onErrorListener onErrorListener) {
        mOnErrorListener = onErrorListener;
    }
}
